Add Kafka event sourcing middleware#185
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: aliok The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
Adds a new Kafka transport for Go Functions that consumes Kafka messages, converts them to CloudEvents, and invokes the same set of supported CloudEvents handler signatures used by the existing cloudevents transport. It also introduces a health-only HTTP server for readiness/liveness probes and exports receiver-function discovery so Kafka can reuse the CloudEvents signature support.
Changes:
- Introduce
kafka/runtime package (service lifecycle, Sarama consumer group loop, Kafka→CloudEvents conversion, health endpoints). - Add unit tests for handler invocation signatures, health endpoints, env-var validation, and CloudEvents pass-through/wrapping behavior.
- Export
cloudevents.GetReceiverFnto reuse CloudEvents handler signature support from the Kafka runtime (and include acmd/fkafkaexample).
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| kafka/service.go | Service lifecycle: starts consumer + health HTTP server; readiness/liveness endpoints; config reading. |
| kafka/service_test.go | Unit tests for readiness/liveness behavior. |
| kafka/message.go | Kafka message/header types used by the consumer and conversion logic. |
| kafka/instance.go | Handler signature validation and invocation across the supported CloudEvents signatures. |
| kafka/handler_test.go | Tests that all supported CloudEvents handler signatures are invokable via Kafka transport. |
| kafka/consumer.go | Sarama consumer group loop plus Kafka message → CloudEvents conversion (including CE header pass-through). |
| kafka/consumer_test.go | Tests for message wrapping, CE pass-through parsing, and missing-env-var validation. |
| cmd/fkafka/main.go | Example binary showing how Kafka transport can run a standard CloudEvents handler. |
| cloudevents/service.go | Switch to exported GetReceiverFn for handler lookup. |
| cloudevents/instance.go | Export GetReceiverFn so other transports (Kafka) can reuse signature support. |
| go.mod | Add Sarama and indirect deps needed for Kafka consumer support. |
| go.sum | Dependency checksum updates for the newly introduced Kafka/Sarama dependency tree. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
and delivers them to the standard CloudEvents handler — no separate handler
signature needed
ce_specversionheaders (CloudEvents Kafka ProtocolBinding, binary content mode) are passed through as-is
dev.knative.kafka.eventand extensions for topic, partition, offset, keyGetReceiverFnfromcloudeventspackage sokafkacan reuse the12 supported handler signatures without duplication
How it works
The
kafka.Start(handler)function accepts any CloudEvents handler (samesignatures as
cloudevents.Start). The scaffoldingmain.gobranches atruntime based on
FUNC_TRANSPORT=kafkaenv var:Configuration is via environment variables set by the func CLI deployer
from
run.kafkainfunc.yaml:KAFKA_BROKERS— comma-separated broker addressesKAFKA_TOPIC— topic to consume fromKAFKA_CONSUMER_GROUP— consumer group IDDelivery semantics
Limitations
Supersedes #169
Closes #183
Testing Kafka Functions End-to-End on Kind
This guide walks through testing the Kafka middleware on a local Kind cluster.
How it works
A CloudEvents function (
invoke: cloudevent) can consume from Kafka by addinga
run.kafkasection tofunc.yaml. The runtime automatically converts Kafkamessages to CloudEvents and delivers them to the same
Handlemethod — no codechanges required.
The deployer/runner sets
FUNC_TRANSPORT=kafkaandKAFKA_BROKERS,KAFKA_TOPIC,KAFKA_CONSUMER_GROUPenv vars automatically from therun.kafkaconfig. The user never needs to set these manually.Limitations
Testing
Prerequisites
1. Build the func CLI
2. Create a Kind cluster with Knative
3. Install Kafka using Strimzi
4. Create a Kafka topic
5. Create the function
This creates a standard CloudEvents function. The generated
function.gohas a
Handle(e event.Event) (*event.Event, error)method — this samehandler will receive Kafka messages wrapped as CloudEvents.
The default template handler doesn't log the incoming event. To see messages
in the logs, add a print statement to
function.go:6. Add Kafka config
Edit
func.yamland add therun.kafkasection:That's all the user needs to do. The deployer translates this to env vars
(
FUNC_TRANSPORT=kafka,KAFKA_BROKERS,KAFKA_TOPIC,KAFKA_CONSUMER_GROUP) on the Knative Service automatically.7. Build and deploy
Manual build (pre-release)
8. Deploy the Knative Service
The
min-scale: "1"annotation keeps the pod running — Kafka consumers muststay up to receive messages.
Wait for the pod:
kubectl wait pods -l serving.knative.dev/service=my-kafka-func --for=condition=Ready --timeout=120s9. Tail function logs
In a separate terminal:
You should see the consumer starting and connecting to Kafka.
10. Send test messages
Plain message (wrapped as CloudEvent)
The function logs should show something like:
Message with key
The function logs should show something like:
CloudEvent message (pass-through)
Messages that already carry CloudEvents headers (
ce_prefix, per theCloudEvents Kafka Protocol Binding binary content mode) are passed through
as-is without re-wrapping. The console producer supports headers via
--property parse.headers=true— input format isheader:value,header:value\t<message body>(tab-separated).The function logs should show the original CE attributes passed through, not
the
dev.knative.kafka.eventwrapper:Cleanup
kubectl delete ksvc my-kafka-func kubectl delete kafka my-cluster -n kafka kubectl delete kafkatopic test-topic -n kafka kubectl delete -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka kubectl delete namespace kafka kind delete cluster --name kafka-test rm -rf /tmp/my-kafka-func /tmp/kafka-func-build /tmp/func-local